package dao

import (
	"context"
	"errors"
	"fmt"

	"bilinadmin/internal/object"

	"bilinadmin/pkg/db/pgex"

	"bilinadmin/internal/model"
)

// StoreDao store dao
type StoreDao interface {
	// CreateStore 创建门店
	CreateStore(ctx context.Context, store *model.Store) (int64, error)
	// UpdateStore 更新门店
	UpdateStore(ctx context.Context, store *model.Store) error
	// GetStoresAbstractByBrand 获取门店列表
	GetStoresAbstractByBrand(ctx context.Context, brandId int64, pg *object.Pagination) ([]*model.Store, uint32, error)
	// SearchStoresAbstract 检索门店列表
	SearchStoresAbstract(ctx context.Context, brandId int64, status int8, busScope, searchName string) ([]*model.Store, error)
	// GetStoreById 根据id获取门店
	GetStoreById(ctx context.Context, storeId int64) (*model.Store, error)
	// GetStoresAbstractByIds 根据id获取门店
	GetStoresAbstractByIds(ctx context.Context, storeIds []int64) ([]*model.Store, error)
	// UpdateStoreSupEmp 更新门店超级管理员
	UpdateStoreSupEmp(ctx context.Context, store *model.Store) error
	// GetStoresBySupEmpId 根据超级管理员获取门店
	GetStoresBySupEmpId(ctx context.Context, brandId, empId int64) ([]*model.Store, error)
	// GetStoresLocationByBrandId 获取门店位置
	GetStoresLocationByBrandId(ctx context.Context, brandId int64) ([]*model.Store, error)
	// GetStoreNamesByBusScope 根据服务范围获取门店
	GetStoreNamesByBusScope(ctx context.Context, brandId int64, cityCode string) ([]*model.Store, error)
}

var storeDao StoreDao

type storeDaoImpl struct {
	*DaoBase
	name string
}

// InitStoreDao 初始化 dao
func InitStoreDao() {
	storeDao = &storeDaoImpl{
		DaoBase: daoBase,
		name:    "store_dao",
	}
}

// GetStoreDao 获取 dao
func GetStoreDao() StoreDao {
	return storeDao
}

// CreateStore 创建门店
func (dao *storeDaoImpl) CreateStore(ctx context.Context, store *model.Store) (int64, error) {
	if store == nil {
		return 0, nil
	}
	param := []interface{}{
		store.BrandId,
		store.Name,
		store.ContactName,
		store.ContactMobile,
		store.BusinessScope,
		store.DistrictCode,
		store.RegionCode,
		store.Address,
		store.Latitude,
		store.Longitude,
		store.Status,
		store.SupEmpId,
		store.ModifyEmpId,
		store.CreatedAt,
		store.UpdatedAt,
	}
	query := "INSERT INTO store (brand_id, name, contact_name, contact_mobile, business_scope, district_code, " +
		"region_code, address, latitude, longitude, status, sup_emp_id, modify_emp_id, created_at, updated_at) " +
		"VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
	aff, err := dao.db.PgExec(ctx, "id", query, param...)
	if err != nil {
		return 0, err
	}
	lastId, _ := aff.GetLastId()
	return lastId, nil
}

// UpdateStore 更新门店
func (dao *storeDaoImpl) UpdateStore(ctx context.Context, store *model.Store) error {
	if store == nil {
		return nil
	}
	param := []interface{}{
		store.Name,
		store.ContactName,
		store.ContactMobile,
		store.BusinessScope,
		store.DistrictCode,
		store.RegionCode,
		store.Address,
		store.Latitude,
		store.Longitude,
		store.UpdatedAt,
		store.Id,
	}
	query := "UPDATE store SET name=?, contact_name=?, contact_mobile=?, business_scope=?, district_code=?, region_code=?, address=?, " +
		"latitude=?, longitude=?, updated_at=? WHERE id=? AND deleted_at=0"
	_, err := dao.db.Update(ctx, query, param...)
	return err
}

// UpdateStoreSupEmp 更新门店超级管理员
func (dao *storeDaoImpl) UpdateStoreSupEmp(ctx context.Context, store *model.Store) error {
	if store == nil || store.Id == 0 || store.SupEmpId == 0 {
		return nil
	}
	query := "UPDATE store SET sup_emp_id=?, updated_at=? WHERE id=? AND deleted_at=0"
	_, err := dao.db.Update(ctx, query, store.SupEmpId, store.UpdatedAt, store.Id)
	return err
}

// GetStoresAbstractByBrand 获取门店概要列表
func (dao *storeDaoImpl) GetStoresAbstractByBrand(ctx context.Context, brandId int64, pg *object.Pagination) ([]*model.Store, uint32, error) {
	where := fmt.Sprintf(" FROM store WHERE brand_id=%d AND deleted_at=0", brandId)
	total, err := dao.CountNum(ctx, where)
	if err != nil {
		return nil, 0, err
	}
	query := fmt.Sprintf("SELECT id, brand_id, name, contact_name, contact_mobile, business_scope, status %s %s", where, pg.GetDbOffset())
	var stores []*model.Store
	err = dao.db.Query(ctx, &stores, query, brandId)
	return stores, total, err
}

// SearchStoresAbstract 检索门店列表
func (dao *storeDaoImpl) SearchStoresAbstract(ctx context.Context, brandId int64, status int8, busScope, searchName string) ([]*model.Store, error) {
	query := "SELECT id, brand_id, name, contact_name, contact_mobile, business_scope, status FROM store WHERE brand_id=? AND deleted_at=0"
	if status != 0 {
		query += fmt.Sprintf(" AND status=%d", status)
	}
	if busScope != "" {
		query += fmt.Sprintf(" AND business_scope LIKE '%dao", busScope) + "%'"
	}
	if searchName != "" {
		query += fmt.Sprintf(" AND (name='%dao' OR contact_name='%dao')", searchName, searchName)
	}
	var stores []*model.Store
	err := dao.db.Query(ctx, &stores, query, brandId)
	return stores, err
}

// GetStoreById 根据id获取门店
func (dao *storeDaoImpl) GetStoreById(ctx context.Context, storeId int64) (*model.Store, error) {
	query := "SELECT * FROM store WHERE id=? AND deleted_at=0"
	store := &model.Store{}
	err := dao.db.Get(ctx, store, query, storeId)
	if err != nil && errors.Is(err, pgex.ErrEmpty) {
		return nil, nil
	}
	return store, err
}

// GetStoresAbstractByIds 根据id获取门店
func (dao *storeDaoImpl) GetStoresAbstractByIds(ctx context.Context, storeIds []int64) ([]*model.Store, error) {
	if len(storeIds) == 0 {
		return nil, nil
	}
	query := "SELECT id, brand_id, name, contact_name, contact_mobile, business_scope, status FROM store WHERE id IN ? AND deleted_at=0"
	var stores []*model.Store
	err := dao.db.Query(ctx, &stores, query, storeIds)
	return stores, err
}

// GetStoresBySupEmpId 根据超级管理员获取门店
func (dao *storeDaoImpl) GetStoresBySupEmpId(ctx context.Context, brandId, empId int64) ([]*model.Store, error) {
	query := "SELECT id, brand_id, name, status, sup_emp_id FROM store WHERE brand_id=? AND sup_emp_id=? AND deleted_at=0"
	var stores []*model.Store
	err := dao.db.Query(ctx, &stores, query, brandId, empId)
	return stores, err
}

// GetStoresLocationByBrandId 获取门店位置
func (dao *storeDaoImpl) GetStoresLocationByBrandId(ctx context.Context, brandId int64) ([]*model.Store, error) {
	var stores []*model.Store
	query := "SELECT id, name, latitude, longitude, address FROM store WHERE brand_id=? AND deleted_at=0"
	err := dao.db.Query(ctx, &stores, query, brandId)
	return stores, err
}

// GetStoreNamesByBusScope 根据服务范围获取门店
func (dao *storeDaoImpl) GetStoreNamesByBusScope(ctx context.Context, brandId int64, cityCode string) ([]*model.Store, error) {
	var stores []*model.Store
	query := "SELECT id, name, business_scope, address FROM store WHERE brand_id=? AND business_scope=? AND deleted_at=0"
	err := dao.db.Query(ctx, &stores, query, brandId, cityCode)
	return stores, err
}
